#include "Logger.h"

#include <iostream>

#include "boost/date_time.hpp"

#pragma warning(push)
#pragma push_macro("_CRT_SECURE_NO_WARNINGS")

#define _CRT_SECURE_NO_WARNINGS
#pragma warning(disable : 4996)

Logger Logger::instance;
bool Logger::initialised = false;

void Logger::initialise(const boost_path& fileName)
{
    if(!initialised)
    {
        instance.fileName = fileName;
        if(!exists(instance.fileName))
        {
            throw std::runtime_error("Invalid logger file name: " +
                instance.fileName.string());
        }
        
        initialised = true;

        // OK to use our own log function now as we're initialised.
        instance.log("Logger initialised.");
    }
    else
    {
        throw std::runtime_error("Logger already initialised.");
    }
}

Logger& Logger::get()
{
	if(!initialised)
	{
        throw std::runtime_error("Logger not initialised.");
	}

	return instance;
}

void Logger::log(const std::string& str)
{
    using namespace boost::posix_time;
    
    // Get local time.
    std::ostringstream msg;
    const ptime now = second_clock::local_time();

    // Convert it to a suitable output format.
    time_facet* const facet = new time_facet("%H-%M-%S-%s");
    msg.imbue(std::locale(msg.getloc(), facet));

    // Store it in a string.
    msg << now;
	std::string as_string(msg.str());

	// Add to log buffer.
	buffer.push_back(str);
}

void Logger::saveLog()
{
	// Make sure that file exists.
	std::fstream stream(fileName.string().c_str(), std::ios_base::in);
	if(!stream)
	{
		throw std::runtime_error("Logger couldn't open " + fileName.string() +
			" for writing.");
	}
	else
	{
		// Load file in out mode.
		stream.close();
		stream.open(fileName.string().c_str(), std::ios_base::out | std::ios_base::trunc);
		for(constBufferIt it = buffer.begin(); it != buffer.end(); ++it)
		{
			// We add the endl here to save space in the buffer.
			stream << *it << std::endl;
		}

		stream.close();
	}	
}

#pragma pop_macro("_CRT_SECURE_NO_WARNINGS")
#pragma warning(pop)